
#include <chrono>
#include <csetjmp>
#include <cstdio>
#include <iostream>
#include <jpeglib.h>
#include <stdio.h>
#include <webp/encode.h>
#include <webp/mux.h>

bool jpeg_to_webp(const char *jpeg_path, const char *webp_path, int quality)
{
    // 1. 读取JPEG文件数据
    struct jpeg_decompress_struct cinfo;
    FILE                         *infile;
    struct jpeg_error_mgr         jerr;
    unsigned char                *rgb_data;

    // ... 初始化libjpeg并解码为RGB数据 ...
    if ((infile = fopen(jpeg_path, "rb")) == NULL) {
        fprintf(stderr, "Error opening file: %s\n", jpeg_path);
        return -1;
    }

    // 初始化解码对象
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    jpeg_stdio_src(&cinfo, infile); // 指定输入源‌
    jpeg_read_header(&cinfo, TRUE); // 读取头信息‌
    jpeg_start_decompress(&cinfo);  // 开始解码‌

    // 获取图像尺寸
    int width  = cinfo.output_width;
    int height = cinfo.output_height;
    // 分配 RGB 缓冲区（每像素3字节）
    rgb_data = (unsigned char *)malloc(width * height * 3);

    unsigned char *row_ptr    = rgb_data;
    int            row_stride = width * 3;
    // 逐行读取扫描线
    while (cinfo.output_scanline < cinfo.output_height) {
        jpeg_read_scanlines(&cinfo, &row_ptr, 1);
        row_ptr += row_stride;
    }

    // 释放资源
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);

    // 2. 配置WebP编码参数
    WebPConfig config;
    WebPConfigInit(&config);
    config.quality = quality; // 质量参数（0-100）
    config.method  = 0;

    // 3. 编码RGB数据为WebP
    WebPMemoryWriter writer;
    WebPMemoryWriterInit(&writer);

    WebPPicture pic;
    WebPPictureInit(&pic);
    pic.width      = cinfo.output_width;
    pic.height     = cinfo.output_height;
    pic.use_argb   = 0; // 使用YUV模式
    pic.writer     = WebPMemoryWrite;
    pic.custom_ptr = &writer;

    auto stime = std::chrono::system_clock::now();
    WebPPictureImportRGB(&pic, rgb_data, row_stride);
    WebPEncode(&config, &pic);
    auto etime = std::chrono::system_clock::now();
    std::cout << "cost: " << std::chrono::duration<double, std::ratio<1, 1000>>(etime - stime).count() << "ms" << std::endl;

    // 4. 写入WebP文件
    FILE *fp = fopen(webp_path, "wb");
    fwrite(writer.mem, 1, writer.size, fp);
    fclose(fp);

    // 5. 释放资源
    WebPPictureFree(&pic);
    WebPMemoryWriterClear(&writer);
    free(rgb_data);
    return true;
}

int main(int argc, char *argv[])
{
    const char *jpeg_path = "input.jpg";
    const char *webp_path = "output.webp";
    jpeg_to_webp(jpeg_path, webp_path, 10);
    return 0;
}
